package store.lunangangster.nodeflow.parser.el;

import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import java.util.ArrayList;
import org.dom4j.Element;
import store.lunangangster.nodeflow.builder.entity.ChainProp;
import store.lunangangster.nodeflow.common.BaseConstant;
import store.lunangangster.nodeflow.exception.RuleSourceParseException;
import store.lunangangster.nodeflow.parser.base.XmlFlowParser;
import store.lunangangster.nodeflow.rt.element.flow.Flow;

/**
 * 用于Xml中EL表达式的解析器，适用于后缀为el.xml的规则文件
 *
 * @author cwk
 * @version 1.0
 */
public class ELXmlFlowParser extends XmlFlowParser {

  private static ExpressRunner runner;

  private static IExpressContext<String, Object> defaultContext;

  public ELXmlFlowParser() {
    runner = ELRunnerHolder.getRunner();
    defaultContext = ELContextHolder.getELContext();
    if (defaultContext == null) {
      defaultContext = new DefaultContext<>();
    }
  }

  @Override
  public ChainProp parseChain(Element chainElement) throws RuleSourceParseException {
    // "id"属性不可为空
    if (chainElement.attribute(BaseConstant.ID) == null) {
      throw new RuleSourceParseException(String.format("Chain parse error: chain have no attribute \"%s\"", BaseConstant.ID));
    }
    String chainId = chainElement.attribute(BaseConstant.ID).getText();
    // 使用中间对象而不是创建一个Chain，防止解析中出现异常而导致需要从FlowBus中将Chain移除
    ChainProp chain = new ChainProp(chainId, new ArrayList<>());
    // 1. 解析<chain/>
    String value = chainElement.getTextTrim();
    try {
      // no check
      Flow flow = (Flow) runner.execute(value, defaultContext, null, true, false);
      chain.addFlow(flow);
      return chain;
    } catch (Exception e) {
      throw new RuleSourceParseException("Chain parse error: EL express parse error " + value, e);
    }
  }
}
